﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using NAcl;
using System.Resources;
using System.IO;
using System.Net;
using System.Reflection;

namespace UIT.Web
{
    public class Context : UIT.Context, IUitContext
    {
        private HttpContext context;
        public Context(HttpContext context)
        {
            this.context = context;
        }

        public HttpContext Http { get { return context; } }

        private class SecurityContext : ISecurityContext
        {
            public System.Security.Principal.IPrincipal User
            {
                get { return ((Context)Current).Http.User; }
            }

            public string[] Roles
            {
                get { return System.Web.Security.Roles.GetRolesForUser(); }
            }
        }

        #region IUitContext Members

        public string Mode
        {
            get { return "Web"; }
        }

        public ISecurityContext Security
        {
            get { return new SecurityContext(); }
        }

        public bool IsAllowed(string resource, string verb)
        {
            return AclManager.IsAllowed(resource, verb, Security.Roles);
        }

        public System.IO.Stream GetStream(Uri uri)
        {
            Stream pageStream = null;

            switch (uri.Scheme)
            {
                case "file":
                    pageStream = File.OpenRead(uri.ToString().Substring("file:///".Length));
                    break;
                case "application":
                    Assembly assembly;
                    if (string.IsNullOrEmpty(uri.Host))
                        if (PageHandlerFactory.ExecutingAssembly == null)
                            assembly = PageHandlerFactory.ExecutingAssembly;
                        else
                            assembly = PageHandler.references[0];
                    else
                        assembly = Assembly.Load(new AssemblyName(uri.Host));

                    if (assembly != null)
                    {
                        byte[] resourceData;
                        string resourceType;
                        new ResourceReader(assembly.GetManifestResourceStream(assembly.GetName().Name + ".g.resources"))
                            .GetResourceData(context.Request.AppRelativeCurrentExecutionFilePath.Substring(2, context.Request.AppRelativeCurrentExecutionFilePath.Length - 3).ToLower(), out resourceType, out resourceData);
                        int length = BitConverter.ToInt32(resourceData, 0);
                        pageStream = new MemoryStream(length);
                        pageStream.Write(resourceData, sizeof(int), length);
                        pageStream.Position = 0;
                    }
                    break;
            }


            if (pageStream == null)
                throw new NotSupportedException("The URI could not be interpreted : " + uri);
            return pageStream;
        }

        public UIT.Application Application
        {
            get { return UIT.Web.Application.application; }
        }

        public Uri ResolveUrl(Uri StartupUri)
        {
            return new Uri(Markup.ResolveUrl.Process(StartupUri.ToString()));
        }

        #endregion

        public Animations.IStoryBoardManager Storyboard
        {
            get { return new StoryboardManager(); }
        }

        public VisualStates.IVisualStateManager VisualState
        {
            get { throw new NotImplementedException(); }
        }

        #region IUitContext Members


        public object this[string key]
        {
            get
            {
                return context.Items[key];
            }
            set
            {
                context.Items[key] = value;
            }
        }

        public RendererManager RendererManager
        {
            get { return (RendererManager)this[typeof(RendererManager).FullName]; }
            internal set { this[typeof(RendererManager).FullName] = value; }
        }

        #endregion
    }
}
